#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

//can_receive_head
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>

//时间戳
#include <time.h>
#define CAN_INTERFACE "can0"  // CAN接口名称
#define MAX_NUM_IDS 5         // 最多可以接收的CAN ID数量
#define MAX_PID 2            //PID数量
#define MAX_FRAME_LEN 200     // 接收到的CAN Frame的最大长度
//int num=0;
// const int array_length = 8; 
/*void writefile(int data[array_length+1],struct tm *p)
{
    char* filename;
    filename=(char*)malloc(60*sizeof(char));
    ++num;
    snprintf(filename,55,"/root/device/home/pi/%d-%d-%d_data%d.txt",p->tm_year+1900,p->tm_mon+1,p->tm_mday,num);
    //int dataindex =ponitnumber;
    int* writedata =data;
    FILE *fp =fopen(filename,"w");
    for(int i=0;i<array_length;i++)
    fprintf(fp,"%d\n",writedata[i]);
    fclose(fp);

}*/
//can_receive
int can_Receive(struct can_frame *x)
{
	 //system("sudo ip link set can0 type can bitrate 2500000");
 	 //system("sudo ifconfig can0 up");

    //判断 J1939还是OBD2
    
    int canSock, err, i;
    fd_set readSet;
    struct ifreq ifr;
    struct sockaddr_can addr;
    char data[MAX_FRAME_LEN];

    // 创建CAN Socket
    canSock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if(canSock < 0) {
        perror("Error while opening socket");
        return -1;
    }

    // 获取CAN接口索引
    strcpy(ifr.ifr_name, CAN_INTERFACE);
    err = ioctl(canSock, SIOCGIFINDEX, &ifr);
    if(err < 0) {
        perror("Error in ioctl");
        return -1;
    }

    // 配置CAN地址
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    // 将Socket绑定到CAN地址
    err = bind(canSock, (struct sockaddr*)&addr, sizeof(addr));
    if(err < 0) {
        perror("Error in socket bind");
        return -1;
    }

    // 设置接收的CAN ID
    struct can_filter rfilter[MAX_NUM_IDS];      // CAN过滤器数组
    int num_ids = 1;                              // 实际需要接收的CAN ID数量
    int can_ids[MAX_NUM_IDS] = {0x7E8};  // 需要接收的CAN ID列表

    if(num_ids > MAX_NUM_IDS) {
        printf("Error: too many CAN IDs");
        return -1;
    }

    for(i = 0; i < num_ids; i++) {
        rfilter[i].can_id = can_ids[i];
        rfilter[i].can_mask = CAN_SFF_MASK;  // 接收所有的SFF（标准帧）消息
    }

    setsockopt(canSock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

    // 主循环接收CAN消息
    int k=0;
    while(1) {
       printf("c start");
        ++k;
        if(k==3)
        {
            printf("k===================3");
            break;
        }
        FD_ZERO(&readSet);                 // 清空读取集合
        FD_SET(canSock, &readSet);         // 加入CAN Socket

        if(select(canSock + 1, &readSet, NULL, NULL, NULL) > 0) {
        if(FD_ISSET(canSock, &readSet)) {  // 有CAN消息到达
            struct can_frame frame;
            err = read(canSock, &frame, sizeof(struct can_frame));  // 读取CAN Frame

            if(err < 0) {
            perror("Error in read");
            continue;
            }

            // 判断当前接收的CAN消息是否是需要的
            for(i = 0; i < num_ids; i++) {
            if(frame.can_id == 0x7E8) {
                printf("Received CAN message with ID 0x%x and length %d\n  Data: ",0x7E8, frame.can_dlc);
                for(int j = 0; j < frame.can_dlc; j++) {
                printf("%02X ", frame.data[j]);
                }
                x->can_dlc=frame.can_dlc;
                for(int i=0;i<frame.can_dlc;++i)
                    x->data[i]=frame.data[i];
                printf("\n");
                close(canSock);
                return 1;
                break;
            }
            }
        }
        }
    }
    close(canSock);
    return 0;
    //6.Close the socket and can0
    
    //return 0;
}
int can_send(struct can_frame* x,int pid)
{
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;
    int s;
    
    if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)        //创建套接字
    {
        perror("Socket");
        return -1;
    }

    strcpy(ifr.ifr_name, CAN_INTERFACE);
    ioctl(s, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    bind(s, (struct sockaddr*)&addr, sizeof(addr));

            

    frame.can_id = 0x7DF;       //发送请求帧
    frame.can_dlc = 0x08;
    frame.data[0] = 0x02;
    frame.data[1] = 0x01;
    frame.data[2] = pid;        //设置PID
    frame.data[3] = 0x00;
    frame.data[4] = 0x00;
    frame.data[5] = 0x00;
    frame.data[6] = 0x00;
    frame.data[7] = 0x00;
    write(s, &frame, sizeof(struct can_frame));
    
    int flag = 0;       //读取响应帧

    // while(flag)
    // {
    //     if(can_receive(x))
    //         flag=false;
    // }
    if(can_Receive(x))
        flag=1;
    close(s);
    if(flag)
        return 1;
    return 0;
}

// void init(int pid[])
// {
//     struct can_frame *f;
//     struct can_frame frame[MAX_PID];
//     f=frame;
//     int length=5;
//     int allPid[length][MAX_PID]={0x05,0x11,0x0C,0x59,0x0D};
//     while(true)
//     {
//         for(int i=0;i<length;++i)
//         {
//             bool flag=true;
//             for(int j=0;j<MAX_PID;++j)
//             {
//                 if(!can_send(f,allPid[i][j]))
//                 {
//                     flag=false;
//                     break;
//                 }
//             }
//             if(flag)
//             {
//                 for(int j=0;j<MAX_PID;++j)
//                     pid[j]=allPid[i][j];
//                 return;
//             }
//         }
//     }
// }
int main(){
    system("sudo ip link set can0 up type can bitrate 500000");
    printf("this is a can receive demo\r\n");
	int i;
    // struct can_frame *f;
    
    struct can_frame frame[MAX_PID];
   
    // f=frame;
    
        //system("sudo ip link set can0 up type can bitrate 250000");
        //system("sudo dhclient -v usb0");
    int a[MAX_FRAME_LEN];
    int bit=0;
    int pid[MAX_PID]={0x0D,0x11};
    // init(pid);
    
    for(int j=0;j<MAX_PID;++j)
    {
        
        if(can_send(&frame[j],pid[j]))
        {
            for(i=bit;i<bit+frame[j].can_dlc;++i)
            {
                a[i]=frame[j].data[i-bit];
                // printf("%02x",a[i]);
                // bit+=frame[j].can_dlc;
            }
            bit=i;
            a[bit]=-pid[j];
            ++bit;
        }
    }
    system("sudo ifconfig can0 down");
    
}